package com.hxh.myAop;

import com.hxh.entity.ProjectDatasource;
import com.hxh.entity.ProjectTablePageConfig;
import com.hxh.service.ProjectConfigRecordService;
import com.hxh.service.ProjectDatasourceService;
import com.hxh.service.ProjectTablePageConfigService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Objects;

/**
 * @author HXH
 * @description: 记录项目版本变更，记录需要操作的类型，如重启、重新生成表代码、重新初始化项目
 */
@Aspect
@Component
@Slf4j
public class ProjectConfigRecordTablePageAspect {

    @Autowired
    private ProjectConfigRecordService projectConfigRecordService;

    @Autowired
    ProjectTablePageConfigService projectTablePageConfigService;
    @Autowired
    ProjectDatasourceService projectDatasourceService;



    /*************************project_table_page_config表 标志处理 start********************************/
    //检查变更字段：projectId、tableName、searchFields、tableColumnFields、addFields、updateFields、showAdd、showBatchAdd、showBatchExport、showDelete、showUpdate

    //判断后台是否需要变更的条件：showBatchAdd、showBatchExport

    /**
     * 环绕拦截 ProjectTablePageConfigService 的 deleteById 方法
     */
    @Around("execution(* com.hxh.service.ProjectTablePageConfigService.deleteById(..)) && args(id)")
    public Object aroundTablePageDeleteById(ProceedingJoinPoint joinPoint, Integer id) throws Throwable {
        // 1. 执行前获取实体
        ProjectTablePageConfig config = null;
        if (id != null) {
            config = projectTablePageConfigService.selectById(id);
        }

        // 2. 执行原方法
        Object result = joinPoint.proceed();

        // 3. 判断是否删除成功
        boolean success = result instanceof Boolean && (Boolean) result;

        if (success && config != null) {
            processAfterPageConfigChange(config);
        }
        return result;
    }

    /**
     * 拦截 ProjectTablePageConfigService 的 insert(ProjectTablePageConfig pojo) 方法
     */
    @AfterReturning(
            pointcut = "execution(* com.hxh.service.ProjectTablePageConfigService.insert(com.hxh.entity.ProjectTablePageConfig)) && args(pojo)",
            returning = "result",
            argNames = "joinPoint,result,pojo"
    )
    public void afterTablePageInsert(JoinPoint joinPoint, boolean result, ProjectTablePageConfig pojo) {
        if (result) {
            processAfterPageConfigChange(pojo);
        }
    }

    /**
     * 环绕拦截 ProjectTablePageConfigService 的 update 方法
     */
    @Around("execution(* com.hxh.service.ProjectTablePageConfigService.update(com.hxh.entity.ProjectTablePageConfig)) && args(pojo)")
    public Object aroundUpdateProjectTablePageConfig(ProceedingJoinPoint joinPoint, ProjectTablePageConfig pojo) throws Throwable {
        // 1. 执行前获取旧数据
        ProjectTablePageConfig oldConfig = null;
        if (pojo.getId() != null) {
            oldConfig = projectTablePageConfigService.selectById(pojo.getId());
        }

        // 2. 执行原方法
        Object result = joinPoint.proceed();

        // 3. 判断是否更新成功
        boolean success = result instanceof Boolean && (Boolean) result;

        if (success) {
            // 4. 对比新旧数据，判断是否需要触发重建逻辑
            if (oldConfig != null) {
                boolean hasChange = hasPropertyChanged(oldConfig, pojo,
                        "projectId", "tableName", "searchFields", "tableColumnFields", "addFields",
                        "updateFields", "showAdd", "showBatchAdd", "showBatchExport",
                        "showDelete", "showUpdate");
                if (hasChange) {
                    processAfterPageConfigChangeForUpdate(oldConfig, pojo);
                }
            }
        }

        return result;
    }

    private void processAfterPageConfigChange(ProjectTablePageConfig pojo) {
        Integer projectId = pojo.getProjectId();
        String tableName = pojo.getTableName();
        ProjectDatasource datasource = projectDatasourceService.selectById(pojo.getDatasourceId());
        String table = datasource.getMysqlDatabaseName() + "." + tableName;

        // 触发前端/后端代码重建
        projectConfigRecordService.frontRebuildTables(projectId, table);
        boolean needBackRebuild = "1".equals(pojo.getShowBatchAdd()) || "1".equals(pojo.getShowBatchExport());
        if (needBackRebuild) {
            projectConfigRecordService.backRebuildTables(projectId, table);
        }

        // 更新项目版本
        projectConfigRecordService.addLocalVersion(projectId);
    }

    private void processAfterPageConfigChangeForUpdate(ProjectTablePageConfig oldOne, ProjectTablePageConfig newOne) {
        Integer oldProjectId = oldOne.getProjectId();
        String oldTableName = oldOne.getTableName();
        ProjectDatasource oldProjectDatasource = projectDatasourceService.selectById(oldOne.getDatasourceId());
        String oldTable = oldProjectDatasource.getMysqlDatabaseName() + "." + oldTableName;

        projectConfigRecordService.frontRebuildTables(oldProjectId, oldTable);
        projectConfigRecordService.addLocalVersion(oldProjectId);

        Integer newProjectId = newOne.getProjectId();
        String newTableName = newOne.getTableName();
        ProjectDatasource newProjectDatasource = projectDatasourceService.selectById(newOne.getDatasourceId());
        String newTable = newProjectDatasource.getMysqlDatabaseName() + "." + newTableName;
        if (!Objects.equals(oldProjectId, newProjectId) || !Objects.equals(oldTableName, newTableName)) {
            projectConfigRecordService.backRebuildTables(oldProjectId, oldTable);
            projectConfigRecordService.frontRebuildTables(newProjectId, newTable);
            projectConfigRecordService.backRebuildTables(newProjectId, newTable);
            if (!Objects.equals(oldProjectId, newProjectId)) {
                projectConfigRecordService.addLocalVersion(newProjectId);
            }
        } else if (!oldOne.getShowBatchAdd().equals(newOne.getShowBatchAdd()) || !oldOne.getShowBatchExport().equals(newOne.getShowBatchExport())) {
            projectConfigRecordService.backRebuildTables(oldProjectId, oldTable);
        }
    }

    /*************************project_table_page_config表 标志处理 end********************************/


    private static boolean hasPropertyChanged(Object oldObj, Object newObj, String... fieldNames) {
        if (oldObj == null && newObj == null) {
            return false;
        }
        if (oldObj == null || newObj == null) {
            return true;
        }
        for (String fieldName : fieldNames) {
            try {
                Field field = oldObj.getClass().getDeclaredField(fieldName);
                field.setAccessible(true);
                Object oldValue = field.get(oldObj);
                Object newValue = field.get(newObj);
                if (!Objects.equals(oldValue, newValue)) {
                    return true;
                }
            } catch (Exception e) {
                log.warn("无法比较字段: {}", fieldName);
            }
        }
        return false;
    }

}
